home *** CD-ROM | disk | FTP | other *** search
- {
- | Icon menu MDEF unit
- |
- | Creates and manages a menu of Icons.
- }
- unit IconMenu;
-
- interface
-
- uses
- Macintf, StdPoll, StdMenu;
-
- type
- IconMenuHdlr = object (MenuHdlr)
- StartIcon, { The resource ID of first icon }
- NumIcons, { How many icons to use (ID's in sequence) }
- IconsWide, { Menu shape... }
- IconsTall, { More menu shape. }
- BufferSpace { Extra white pixels around each icon }
- : Integer;
- Title { The name of the menu }
- : Str255;
-
- procedure Create (RsrcID : Integer); override;
- procedure Setup (
- StartIconReq,
- NumIconsReq,
- IconsWideReq,
- BufferSpaceReq
- : Integer;
- TitleReq
- : Str255); end;
-
- IconMenuPtr = ^IconMenuInfo;
- IconMenuHandle = ^ IconMenuPtr;
-
- IconMenuInfo = record
- StdStuff : MenuInfo; { The default MenuInfo record }
- Handler : IconMenuHdlr { Reference to the above handler object }
- end;
-
- {------------------------------------------------------------------------}
- implementation
-
- const
- IconSize = 32; { How big is an icon }
-
- {
- | IconMenuDef is installed as the MDEF procedure.
- | See IM Vol. I, p. 362
- }
- procedure IconMenuDef (
- Message : Integer;
- SelectedMenu : IconMenuHandle;
- var MenuRect : Rect;
- HitPt : Point;
- var WhichItem : Integer);
-
- {
- | ItemRect - function to find the rectangle ( in global
- | coordinates) of a given item number.
- }
- function ItemRect (
- ItemNum : Integer;
- MenuRect : Rect;
- SelectedMenu : IconMenuHandle) : Rect;
-
- var
- TempRect
- : Rect;
- ItemLess1,
- ItemSize
- : Integer;
-
- begin
- { If ItemNum is a real item, then return the }
- { global coordinates of the item's rectangle; }
- { otherwise return empty rect. }
- if (ItemNum >= 1)
- and (ItemNum <= SelectedMenu^^.Handler.NumIcons)
- then with SelectedMenu^^.Handler do begin
- ItemLess1 := ItemNum - 1;
- ItemSize := IconSize + 2 * BufferSpace;
- TempRect.top := (ItemLess1 div IconsWide)
- * ItemSize + MenuRect.top;
- TempRect.left := (ItemLess1 mod IconsWide)
- * ItemSize + MenuRect.left;
- TempRect.bottom := TempRect.top + ItemSize;
- TempRect.right := TempRect.left + ItemSize end
- else begin
- TempRect.top := 0;
- TempRect.left := 0;
- TempRect.bottom := 0;
- TempRect.right := 0 end;
- ItemRect := TempRect end;
-
- {
- | DoDrawMessage - handle the menu manager Draw command
- }
- procedure DoDrawMessage (
- SelectedMenu : IconMenuHandle;
- MenuRect : Rect);
-
- var
- Selection : Integer; { Current selection }
- SelRect : Rect; { Current selection's Rectangle }
- TheIcon : Handle; { Handle to the selection's Icon }
-
- begin
- { Get every icon in the menu and plot it. }
- Hlock(Handle(SelectedMenu));
- with SelectedMenu^^.Handler do begin
- for Selection := 1 to NumIcons do begin
- SelRect := ItemRect(Selection, MenuRect, SelectedMenu);
- InsetRect(SelRect,BufferSpace,BufferSpace);
- TheIcon := GetIcon (StartIcon + Selection - 1);
- PlotIcon (SelRect, TheIcon) end end;
- HUnlock(Handle(SelectedMenu)) end;
-
- {
- | DoChooseMessage - handle the menu manager Choose command
- }
- function DoChooseMessage (
- SelectedMenu : IconMenuHandle;
- MenuRect : Rect;
- HitPoint : Point;
- OldSelection : Integer) : Integer;
- var
- SelRect : Rect;
- Found : boolean;
- Selection : Integer;
- OldSelRect : Rect;
- begin
- Selection := 1;
- Found:= false;
- { Find out which item mouse is over, if any. }
- repeat
- SelRect := ItemRect (Selection, MenuRect, SelectedMenu);
- Found := PtInRect (HitPoint,SelRect);
- if not Found
- then Selection := Selection + 1;
- until ((Selection > (SelectedMenu^^.Handler.NumIcons))
- or (Found));
- { Update hiliting as necessary }
- if Found
- then begin { in an item }
- if (Selection <> OldSelection)
- then begin { in a different item, change hiliting }
- OldSelRect := ItemRect(OldSelection,
- MenuRect, SelectedMenu);
- InvertRect(OldSelRect);
- InvertRect(SelRect) end;
- DoChooseMessage := Selection end
- else begin { not in a item, unhilite old }
- OldSelRect := ItemRect(OldSelection, MenuRect, SelectedMenu);
- InvertRect (OldSelRect);
- DoChooseMessage := 0 end end;
-
- {
- | DoSizeMessage - handle the menu manager Size command
- }
- procedure DoSizeMessage (
- var Menu : IconMenuHandle);
- begin
- with Menu^^.Handler do begin
- Menu^^.StdStuff.menuWidth
- := IconsWide*(IconSize + 2 * BufferSpace);
- Menu^^.StdStuff.menuHeight
- := IconsTall*(IconSize + 2 * BufferSpace)
- end end;
-
- {
- | IconMenuDef - main
- }
- begin
- case message of
- mSizeMsg : DoSizeMessage (SelectedMenu);
- mDrawMsg : DoDrawMessage (SelectedMenu, MenuRect);
- mChooseMsg : WhichItem := DoChooseMessage (
- SelectedMenu,MenuRect,HitPt,WhichItem) end end;
-
- function Min (a,b : Integer) : Integer;
- begin
- if a < b
- then Min := a
- else Min := b end;
-
- procedure IconMenuHdlr.Setup (
- StartIconReq,
- NumIconsReq,
- IconsWideReq,
- BufferSpaceReq
- : Integer;
- TitleReq
- : Str255);
- begin
- StartIcon := StartIconReq;
- NumIcons := NumIconsReq;
- IconsWide := IconsWideReq;
- { Calculate IconsTall from NumIcons and IconsWide }
- IconsTall := NumIcons div IconsWide
- + Min (NumIcons mod IconsWide, 1);
- BufferSpace := BufferSpaceReq;
- Title := TitleReq end;
-
- procedure IconMenuHdlr.Create (RsrcID : Integer);
- { RsrcID isn't really a resource ID in this case, just a menu id }
- var
- TrickyHandle : IconMenuHandle; { Used for type coercion }
-
- begin
- HLock(Handle(Self));
- TheMenu := NewMenu (RsrcID, Title); { Get a plain menu record }
-
- SetHandleSize (Handle(TheMenu), SizeOf(IconMenuInfo)); { Stretch it }
- if MemError = 0
- then begin
- { Assign the icon MDEF proc }
- TheMenu^^.menuProc := NewHandle(0); { Very Important! }
- TheMenu^^.menuProc^ := @IconMenuDef;
- { Stuff in reference to the MenuHandler object }
- TrickyHandle := IconMenuHandle (TheMenu);
- TrickyHandle^^.Handler := SELF;
- { Insert at end of menu bar }
- CalcMenuSize (TheMenu);
- InsertMenu (TheMenu,0) end
- else
- SysBeep (1);
- HUnlock(Handle(Self)) end;
-
- end. { of IconMenu unit }
-